#!/usr/bin/python

from multiplylib import *
import copy

# ============================== for 8x8/16x16 mix multiply ==============================
dots_grid_init(cols=32, rows=14)

dots_8x8_L = gen_pp(mcand_width=8, mplier_width=8, prefix="", pp0_height_reduction=False)
# set the last pp (not pp[4] but pp_8_L[4])
pp_8_L_4 = [("pp_8_L[4][%d]" % i,False) for i in range(8)]
set_pp(dots_8x8_L, row=5, start_col=8, pp_val=pp_8_L_4)
# the third operand for madd/msub
# wd_L = [("op_c[%d]" % i,True) for i in range(8)]
wd_L = [("(~i_mode_q & op_c[%d])" % i,True) for i in range(8)]     # add ~i_mode_q for simplify when in 16x16 mode
set_pp(dots_8x8_L, row=6, start_col=0, pp_val=wd_L)
# strip part of the sign compensation to avoid carry bit from low 8x8(low 16bits) to high 8x8(high 16bits)
set_dots_cell(dots_8x8_L, (0, 9), ("i_dotp", True))
set_dots_cell(dots_8x8_L, (1, 10), ("i_dotp", True))
set_dots_cell(dots_8x8_L, (2, 12), ("i_dotp", True))
set_dots_cell(dots_8x8_L, (3, 14), ("i_dotp", True))

# new_fig()
# display_dots(dots_8x8_L, style="text")

# the dots only for "dot product"
dots_8x8_H_orig = gen_pp(mcand_width=8, mplier_width=8, prefix="", pp0_height_reduction=False, pp_index_start=(4,8))
# the third operand for madd/msub
# wd = [("op_c[%d]" % i,False) for i in range(16)]
# set_pp(dots_8x8_H_orig, row=6, start_col=0, pp_val=wd)
wd_H = [("op_c[%d]" % i,False) for i in range(8,15+1)]
set_pp(dots_8x8_H_orig, row=6, start_col=8, pp_val=wd_H) # only need the high part since low part is added in dots_8x8_L
# set switch for dot product
dots_dotp_only = set_switch(dots_8x8_H_orig, "i_dotp") # the dots of dots_8x8_H_orig only valid when i_dotp asserted ("and" operation)

# the high 8x8 (only preverse the low 8 bits of the product)
dots_8x8_H = gen_pp(mcand_width=8, mplier_width=8, prefix="", pp0_height_reduction=True, pp_index_start=(4,8)) 
# the third operand for madd/msub
wd_H = [("op_c[%d]" % i,False) for i in range(8,15+1)]
set_pp(dots_8x8_H, row=5, start_col=0, pp_val=wd_H)
# strip the high half bits (not-care terms)
for col in range(8,15+1):
    for row in range(12):
        set_dots_cell(dots_8x8_H, (row, col), (0, False))
shift_left(dots_8x8_H, 16)

dots_8x8 = add_dots(dots_8x8_L, dots_dotp_only, dots_8x8_H)
# dots_8x8 = add_dots(dots_8x8_L, dots_8x8_H)

# set_dots_cell(dots_8x8, 3, 14, ("i_dotp", True)) # this cell must be "i_dotp"
# # at least one of bellow cells should be set
# set_dots_cell(dots_8x8, 0, 9, ("i_dotp", True))
# set_dots_cell(dots_8x8, 1, 10, ("i_dotp", True))
# set_dots_cell(dots_8x8, 2, 12, ("i_dotp", True))


new_fig()
display_dots(dots_8x8, style="text")

mark_dots(start_dot=(1,7), end_dot=(6,0), color="red")
mark_dots(start_dot=(0,23), end_dot=(5,16), color="red")
mark_dots(start_dot=(0,15), end_dot=(13,0), color="blue")

mark_dots(start_dot=(3,14), color="green")
mark_dots(start_dot=(0,9), color="green")
mark_dots(start_dot=(1,10), color="green")
mark_dots(start_dot=(2,12), color="green")

mark_dots(start_dot=(7,9), color="green")
mark_dots(start_dot=(8,10), color="green")
mark_dots(start_dot=(9,12), color="green")
mark_dots(start_dot=(10,14), color="green")



# simplify the i_dotp variable
set_dots_cell(dots_8x8, (0, 9), (0, False))
set_dots_cell(dots_8x8, (1, 10), (0, False))
set_dots_cell(dots_8x8, (2, 12), (0, False))
set_dots_cell(dots_8x8, (3, 14), (0, False))

set_dots_cell(dots_8x8, (7, 9), (0, False))
set_dots_cell(dots_8x8, (8, 10), (0, False))
set_dots_cell(dots_8x8, (9, 12), (0, False))
set_dots_cell(dots_8x8, (10, 14), (0, False))

set_dots_cell(dots_8x8, (8, 15), ("i_dotp", True))
set_dots_cell(dots_8x8, (8, 13), ("i_dotp", True))
set_dots_cell(dots_8x8, (8, 11), ("i_dotp", True))
set_dots_cell(dots_8x8, (8, 10), ("i_dotp", True))


new_fig()
display_dots(dots_8x8, style="text")

mark_dots(start_dot=(1,7), end_dot=(6,0), color="red")
mark_dots(start_dot=(0,23), end_dot=(5,16), color="red")
mark_dots(start_dot=(0,15), end_dot=(13,0), color="blue")

mark_dots(start_dot=(8,15), end_dot=(8,10), color="green")


dots_8x8_orig = copy.deepcopy(dots_8x8)
# re-organize
dots_1 = cut_dots(dots_8x8, start_dot=(8,15), end_dot=(13,0))
dots_2 = cut_dots(dots_8x8, start_dot=(6,7), end_dot=(6,0))
dots_3 = cut_dots(dots_8x8, start_dot=(0,23), end_dot=(5,16))
dots_4 = cut_dots(dots_8x8, start_dot=(1,15), end_dot=(5,0))
dots_8x8 = add_dots(dots_1, dots_2, dots_3, dots_4)

new_fig()
display_dots(dots_8x8, style="text")
mark_dots(start_dot=(0,23), end_dot=(5,0), color="red")
mark_dots(start_dot=(6,15), end_dot=(10,0), color="blue")




# 16x16 for Half word insn or fixed-point insn
dots_16x16 = gen_pp(mcand_width=16, mplier_width=16, prefix="")
# integer madd/msub (~i_mode_q)
wd = [("(~i_mode_q & op_c[%d])" % i,True) for i in range(16)]
set_pp(dots_16x16, row=9, start_col=0, pp_val=wd)
# fixed point madd/msub and round
wd_q = [("msub_q",True) for i in range(14)]
wd_q.append(("(round_q^msub_q)", True)) # or: wd_q.append(("(round_q^i_msub)", True))
#wd_q += [("op_c[%d]" % i,True) for i in range(16)]
wd_q.append(("(i_mode_q & op_c[0])", True))
wd_q += [("op_c[%d]" % i,True) for i in range(1,16)]
wd_q.append(("op_c[15]", True))
set_pp(dots_16x16, row=10, start_col=0, pp_val=wd_q)


new_fig("16x16")
display_dots(dots_16x16)

mark_dots(start_dot=(9,0), end_dot=(9,15), color="red")
mark_dots(start_dot=(10,0), end_dot=(10,31), color="blue")
# the last pp
mark_dots(start_dot=(8,16), end_dot=(8,31), color="green")

# strip the last PP (it's 0 when in signed mode)
for col in range(16,31+1):
    set_dots_cell(dots_16x16, (8, col), (0, False))

new_fig()
display_dots(dots_16x16)


# mix the 8x8 and 16x16 dots
dots_8x8_up = reorg_upward(dots_8x8)
dots_16x16_up = reorg_upward(dots_16x16)

new_fig()
display_dots(dots_8x8_up, style="dot")
display_dots(dots_16x16_up, fill=False, color="red", style="dot")


# process the not-care term
for col in range(24,31+1):
    for row in range(12):
        dots_8x8_up[row][col] = dots_16x16_up[row][col]

dots_mix, dots_mix_distr = mix_dots(dots_8x8_up, dots_16x16_up, "mode8", sort_cols=False)

new_fig()
display_dots_distribute(dots_mix_distr)


# strip the redundancy term
def dot_process(item):
    if item.find("(mode8 & (i_dotp &") == 0:
        return item[9:-1]
    # elif item.find("(~mode8 & (~i_mode_q &") == 0:
    #     return item[10:-1])


traverse_dots(dots_mix, dot_process)



new_fig()
display_dots(dots_mix, style="text")


print "==================== row formula of 8x8/16x16 mix multiply ===================="
print_row_formula(dots_mix, prefix="assign pp_ext")
print "==============================================================================="



show()
exit()

